namespace	Z	{

//------------------------------------------------------------------------------------------------------------------------
template<typename Fetcher, typename Builder>
MessageController<Fetcher, Builder>::MessageController(NetworkController* pNetworkController, MessageHandler* pMessageHandler)
:	mNetworkController(pNetworkController),
	mMessageHandler(pMessageHandler)
{
}

template<typename Fetcher, typename Builder>
MessageController<Fetcher, Builder>::~MessageController()
{
}

template<typename Fetcher, typename Builder>
bool MessageController<Fetcher, Builder>::start()
{
	return mNetworkController->start(this);
}

template<typename Fetcher, typename Builder>
void MessageController<Fetcher, Builder>::cleanup()
{
	mNetworkController->cleanup();

	cleanupMessages();
}

template<typename Fetcher, typename Builder>
void MessageController<Fetcher, Builder>::cleanupMessages()
{
	NetworkMessage* pMessage	= nullptr;
	while(mMessages.try_pop(pMessage))	{
		deletePtr(pMessage);
	}
}

template<typename Fetcher, typename Builder>
void MessageController<Fetcher, Builder>::onConnect(NetworkId kNetworkId)
{
	addMessage(createConnectMessage(kNetworkId));
}

template<typename Fetcher, typename Builder>
void MessageController<Fetcher, Builder>::onDisconnect(NetworkId kNetworkId)
{
	addMessage(createDisconnectMessage(kNetworkId));
}

template<typename Fetcher, typename Builder>
void MessageController<Fetcher, Builder>::onReceive(NetworkReceiveBuffer& kBuffers, NetworkReceiver& kNetworkReceiver)
{
	NetworkGenericMessage* pMessage	= Fetcher::fetch(kBuffers, kNetworkReceiver);
	while(pMessage != nullptr)	{
		addMessage(pMessage);
		pMessage	= Fetcher::fetch(kBuffers, kNetworkReceiver);
	}
}

template<typename Fetcher, typename Builder>
void MessageController<Fetcher, Builder>::send(void* data, size_t dataSize, NetworkId kNetworkId)
{
	NetworkGenericMessage* pMessage	= Builder::build(data, dataSize, kNetworkId);
	mNetworkController->send(pMessage->detach(), pMessage->getNetworkId());
	deletePtr(pMessage);
}

template<typename Fetcher, typename Builder>
void MessageController<Fetcher, Builder>::execute()
{
	NetworkMessage* pMessage	= nullptr;
	while(mMessages.try_pop(pMessage))	{
		pMessage->pump(*mMessageHandler);
		deletePtr(pMessage);
	}
}

template<typename Fetcher, typename Builder>
void MessageController<Fetcher, Builder>::addMessage(NetworkMessage* pMessage)
{
	mMessages.push(pMessage);
}

template<typename Fetcher, typename Builder>
NetworkMessage* MessageController<Fetcher, Builder>::createConnectMessage(NetworkId kNetworkId)
{
	return new NetworkConnectMessage(kNetworkId);
}

template<typename Fetcher, typename Builder>
NetworkMessage* MessageController<Fetcher, Builder>::createDisconnectMessage(NetworkId kNetworkId)
{
	return new NetworkDisconnectMessage(kNetworkId);
}

template<typename Fetcher, typename Builder>
void MessageController<Fetcher, Builder>::shutdown(NetworkId kNetworkId)
{
	mNetworkController->shutdown(kNetworkId);
}

}